﻿using PoemGame.Domain.GameAggregate;
using PoemGame.Domain.PlayerAggregate;
using PoemGame.Domain.Services;
using PoemGame.ApplicationService;

namespace ConsoleDemo.Application
{
    public class ConsoleDemoAppService : IConsoleDemoAppService
    {
        private readonly IGameFactory _factory;
        private readonly IGameRepository _gameRepository;
        private readonly IPlayerRepository _playerRepository;
        private readonly IDomainServiceFactory<ICheckAnswerService> _checkAnswerServiceFactory;

        public ConsoleDemoAppService(IGameFactory factory, 
            IGameRepository gameRepository,
            IPlayerRepository playerRepository,
            IDomainServiceFactory<ICheckAnswerService> checkAnswerServiceFactory)
        {
            _factory = factory;
            _gameRepository = gameRepository;
            _playerRepository = playerRepository;
            _checkAnswerServiceFactory = checkAnswerServiceFactory;
        }

        public async Task<GameCreateResult> CreateGameAsync(GameType gameType, string context)
        {
            var playerme=await AddPlayer("我自己");
            var playercomputer=await AddPlayer("计算机");
            var res = new GameCreateResult();
            var game = await _factory.CreateGame(playerme, gameType,PlayType.Inturn, "", context);
            res.IsSuccess = game.IsSuccess;
            res.Message=game.Message;
            if (game.IsSuccess)
            {
                res.GameId = game.CreatedGame.Id;
                game.CreatedGame.PlayerJoinGame(playercomputer);
                await _gameRepository.AddAsync(game.CreatedGame);
                game.CreatedGame.Start();
            }
            return res;
        }

        public async Task<string> GetCurrentUser(Guid gameId)
        {
            var game = await _gameRepository.GetAsync(gameId);
            var cp= game.GetCurrentPlayer();
            var player= await _playerRepository.GetPlayerByIdAsync(cp.PlayerId);
            return player.UserName;
        }

        public async Task<string> GetLastPropertyAnswerAsync(Guid gameId)
        {
            var game=await _gameRepository.GetAsync(gameId);
            var lst = game.GetProperAnswers().OrderBy(o => o.PlayDateTime);
            if (lst.Any())
            {
                return lst.Last().Answer;
            }
            return game.GameCondition;
        }

        public async Task<GamePlayResult> PlayAsync(Guid gameId, string answer)
        {
            var game = await _gameRepository.GetAsync(gameId);
            var playcurr=game.GetCurrentPlayer();
            var player = await _playerRepository.GetPlayerByIdAsync(playcurr.PlayerId);
            var isproperty=await game.Play(player, answer, _checkAnswerServiceFactory);
            
            var res=new GamePlayResult();
            if (isproperty)
            {
                res.IsFinish = false;
                res.Message = player.UserName + "回答正确";
                playcurr.PlayerStatus = PlayerGameStatus.Waiting;
            }
            else
            {
                playcurr.PlayerStatus = PlayerGameStatus.Out;
                res.Message = player.UserName + "出局";
            }
            var activateplayers = game.GetWaitingPlayers();
            if (activateplayers.Count == 1 && isproperty)
            {
                var activateplayer = await _playerRepository.GetPlayerByIdAsync(activateplayers[0].PlayerId);
                res.Message += $"游戏结束,{activateplayer.UserName}获胜";
                game.GameOver(activateplayer);
                
                res.IsFinish = true;
            }
            else if (activateplayers.Count == 0)
            {
                //游戏结束，没有赢家
                res.Message += $"游戏结束,没有赢家";
                game.GameOver();
               
                res.IsFinish = true;
            }
            else
            {
                var nextplayer = game.GetNextPlayer(player.Id);
                game.SetPlayerInturn(nextplayer.PlayerId);

                var nplayer = await _playerRepository.GetPlayerByIdAsync(nextplayer.PlayerId);
                res.Message += $"轮到{nplayer.UserName}回答问题";
            }
            return res;
        }

        private async Task<Player> AddPlayer(string playerName)
        {
            var player= await _playerRepository.GetPlayerByUserNameAsync(playerName);
            if (player == null) player = new Player( Guid.NewGuid(),  playerName ,playerName,0);
            await _playerRepository.AddAsync(player);
            return player;
        }
    }
}
